package Logic.Objects;
import java.util.Hashtable;
import java.util.Random;
import Exceptions.StrategoException;
import Logic.IPlayer;
import Logic.Square;
import Logic.MoveResults.MoveResultsType;
import Logic.Square.Rank;

public class Player implements IPlayer {
	private Integer ID;
	private String name;
	private Boolean isAlive;
	private Type type;
	private Hashtable<Square,Data> AIDB = null;
	private MoveResultsType lastEvent = MoveResultsType.move;
	
	public Player(String name,Type type, int playerNum) {
		isAlive = true;
		this.name = name;
		ID = playerNum;
		this.type = type;
		AIDB = (type == Type.human) ? null : new Hashtable<Square,Data>(); 
	}
	public MoveResultsType getLastEvent()
	{
		return lastEvent;
	}
	public void setLastEvent(MoveResultsType evnt)
	{
		lastEvent = evnt; 
	}
	public int getID() {
		// TODO Auto-generated method stub
		return ID;
	}

	public String getName() {
		// TODO Auto-generated method stub
		return name;
	}

	public boolean isAlive() {
		// TODO Auto-generated method stub
		return isAlive;
	}

	public void killPlayer() {
		isAlive = false;

	}
	public boolean isHuman()
	{
		return (type==Type.human);
	}
	public Type getType()
	{
		return type;
	}
	public void setAI()
	{
		type = Type.AI;
		AIDB = new Hashtable<Square,Data>();
	}
	public void setHuman()
	{
		type = Type.human;
		AIDB = null;
	}

	public void clone(IPlayer src)
	{
		this.ID = src.getID();
		this.isAlive = src.isAlive();
		this.name = src.getName();
		this.type = src.getType();
	}
	public void setName(String name)
	{
		this.name = name;
	}

	// AI related functions
	public Move AIGenerateNextMove(Square[][] board) throws StrategoException 
	{
		Move move = null;
		int temp = 0;
		int max = 0;

		for (int y=1;y<=18;y++)
			for (int x=1;x<=18;x++)
			{
				Square square = board[x-1][y-1];
				if ( !(square.getType().equals(Logic.Square.Type.Soldier)) ) continue; //not a soldier

				if (square.getPlayerId() != ID) continue;      // not ours

				// our soldier and it can move - lets give him scores
				Rank rank = square.getRank();

				// cant move the flag or bomb

				if ( (rank == Rank.Flag) || (rank == Rank.Bomb) ) continue;


				for (int i=-1;i<=1;i++)
					for (int j=-1;j<=1;j++)
					{
						if  ( ( Math.abs(i) + Math.abs(j) ) != 1) continue;
						// calculate sides
						temp = 0;

						Square nextSquare = null;
						
						if ( ( (x+j-1)>0 ) && (x+j-1<18) && (y+i-1>0) && (y+i-1<18)  ) 
							nextSquare = board[x+j-1][ y+i-1];
						

						if ( (nextSquare == null ) || 
							( ( nextSquare.getType()==Square.Type.Soldier)  && (nextSquare.getPlayerId() == ID) )
							|| (!nextSquare.isWalkable()))  continue; //cant move on your own
						
		
						
						
							temp = calculateOdds(square,nextSquare,board);

							if (temp>max)
							{
								if (move==null)
									move = new Move();

								max = temp;
								move.old_x = x;
								move.old_y = y;
								move.new_x = x+j;
								move.new_y = y+i;
							}

						
					}

			}
		
		return move;
	}
	public int calculateOdds(Square square,Square nextSquare,Square[][] engine)
	{
		int score = 0;
		Random rand = new Random();
		
		// first calculate your rank
		score += square.getRank().getId();
		if  ( (nextSquare.getType().equals(Logic.Square.Type.Soldier)) &&
				( nextSquare ).getPlayerId() != ID) 
			score += 10;

		score += rand.nextInt(5);
		
		return score;
	}
	public void AIUpdateDB(Square srcSquare,Square destSquare,int dist,Logic.MoveResults result)
	{
		//nothing to do if its our move
		if (srcSquare.getPlayerId() == ID)
			return;
		
		Data srcData = AIDB.get(srcSquare);
		Data destData = AIDB.get(destSquare);
		
		
		switch (result.getType())
		{
		// handles the conclusions regarding move 
		case move:
			if (srcData == null)
			{
				srcData = new Data();
				AIDB.put(srcSquare, srcData);
			}
			srcData.totalMoves++;
			
			// must be a scout
			if (dist>1)
				srcData.rank = Rank.Scout;
			break;
			
		case win:
			if (srcData == null)
			{
				srcData = new Data();
				AIDB.put(srcSquare, srcData);
			}
			
			srcData.totalWins++;
			
			if (destData != null)
				AIDB.remove(destData);
			
			break;
			
			
		case tie:
			break;
			
			
		case lose:
			break;
		
		}	
	}

	private class Data
	{
		Rank rank = Rank.Unknown;
		int totalMoves = 0;
		int totalFights = 0;
		int totalWins = 0;
		
	}
}